package com.nbsaas.nbmall.product.rest.resource;

import com.nbsaas.nbmall.product.api.apis.ProductApi;
import com.nbsaas.nbmall.product.api.domain.list.ProductList;
import com.nbsaas.nbmall.product.api.domain.page.ProductPage;
import com.nbsaas.nbmall.product.api.domain.request.*;
import com.nbsaas.nbmall.product.api.domain.response.ProductResponse;
import com.nbsaas.nbmall.product.api.domain.simple.ProductImageSimple;
import com.nbsaas.nbmall.product.api.domain.simple.ProductSkuSimple;
import com.nbsaas.nbmall.product.api.domain.vo.ProductSpecValueVo;
import com.nbsaas.nbmall.product.api.domain.vo.ProductSpecVo;
import com.nbsaas.nbmall.product.data.dao.*;
import com.nbsaas.nbmall.product.data.entity.*;
import com.nbsaas.nbmall.product.data.enums.ProductState;
import com.nbsaas.nbmall.product.data.enums.ProductType;
import com.nbsaas.nbmall.product.listener.ProductChangeListener;
import com.nbsaas.nbmall.product.rest.convert.ProductResponseConvert;
import com.nbsaas.nbmall.product.rest.convert.ProductSimpleConvert;
import com.haoxuer.bigworld.tenant.data.entity.Tenant;
import com.haoxuer.discover.config.utils.ConverResourceUtils;
import com.haoxuer.discover.data.page.Filter;
import com.haoxuer.discover.data.page.Order;
import com.haoxuer.discover.data.page.Page;
import com.haoxuer.discover.data.page.Pageable;
import com.haoxuer.discover.data.utils.FilterUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.haoxuer.bigworld.member.rest.conver.PageableConver;
import com.haoxuer.bigworld.tenant.util.TenantBeanUtils;
import com.haoxuer.bigworld.member.data.dao.TenantUserDao;
import com.nbsaas.nbmall.shop.data.dao.ShopDao;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Transactional
@Component
public class ProductResource implements ProductApi {

    @Autowired
    private ProductDao dataDao;

    @Autowired
    private TenantUserDao creatorDao;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private ProductGroupDao productGroupDao;
    @Autowired
    private ProductCatalogDao productCatalogDao;

    @Autowired
    private ProductImageDao imageDao;

    @Autowired
    private ProductSpecDao specDao;

    @Autowired
    private ProductSpecValueDao specValueDao;

    @Autowired
    private ProductSkuDao skuDao;

    @Autowired(required = false)
    private List<ProductChangeListener> changeListeners;

    @Override
    public ProductResponse create(ProductDataRequest request) {
        ProductResponse result = new ProductResponse();

        Product bean = new Product();
        bean.setTenant(Tenant.fromId(request.getTenant()));
        handleData(request, bean);
        dataDao.save(bean);
        result = new ProductResponseConvert().conver(bean);

        //处理图片
        if (request.getImages() != null && request.getImages().size() > 0) {
            for (ProductImageSimple item : request.getImages()) {
                ProductImage image = new ProductImage();
                image.setProduct(bean);
                image.setUrl(item.getUrl());
                image.setTenant(bean.getTenant());
                imageDao.save(image);
            }
        }

        //处理规格
        if (request.getSpecs() != null && request.getSpecs().size() > 0) {
            for (ProductSpecVo spec : request.getSpecs()) {
                ProductSpec ProductSpec = new ProductSpec();
                ProductSpec.setProduct(bean);
                ProductSpec.setName(spec.getName());
                ProductSpec.setTenant(bean.getTenant());
                specDao.save(ProductSpec);
                if (spec.getValues() != null && spec.getValues().size() > 0) {
                    for (ProductSpecValueVo value : spec.getValues()) {
                        ProductSpecValue specValue = new ProductSpecValue();
                        specValue.setProductSpec(ProductSpec);
                        specValue.setValue(value.getName());
                        specValue.setTenant(bean.getTenant());
                        specValueDao.save(specValue);
                    }
                }

            }
        }

        //处理sku
        if (request.getSkus() != null && request.getSkus().size() > 0) {
            for (ProductSkuSimple item : request.getSkus()) {
                ProductSku sku = new ProductSku();
                if (item.getSalePrice() == null) {
                    item.setSalePrice(new BigDecimal(0));
                }
                if (item.getMarketPrice() == null) {
                    item.setMarketPrice(new BigDecimal(0));
                }
                sku.setSalePrice(item.getSalePrice());
                sku.setName(item.getName());
                sku.setMarketPrice(item.getMarketPrice());
                sku.setSpec(item.getSpec());
                sku.setProduct(bean);
                sku.setTenant(bean.getTenant());
                skuDao.save(sku);
            }
            List<BigDecimal> moneys = request.getSkus().stream().map(item -> item.getSalePrice()).collect(Collectors.toList());
            BigDecimal min = moneys.stream().min(new Comparator<BigDecimal>() {
                @Override
                public int compare(BigDecimal bigDecimal, BigDecimal t1) {
                    return bigDecimal.compareTo(t1);
                }
            }).get();

            BigDecimal max = moneys.stream().max(new Comparator<BigDecimal>() {
                @Override
                public int compare(BigDecimal bigDecimal, BigDecimal t1) {
                    return bigDecimal.compareTo(t1);
                }
            }).get();
            bean.setMinPrice(min);
            bean.setMaxPrice(max);
            bean.setProductType(ProductType.sku);
            bean.setSkuEnable(true);
            bean.setSalePrice(min);
        } else {
            bean.setProductType(ProductType.spu);
            bean.setSkuEnable(false);
        }


//        bean.setAttrs(new HashSet<>());
//        //处理属性
//        if (request.getAttrs() != null && request.getAttrs().size() > 0) {
//            for (Long attr : request.getAttrs()) {
//                ProductAttrValue value = attrValueDao.findById(attr);
//                if (value != null) {
//                    bean.getAttrs().add(value);
//                }
//            }
//        }


        if (changeListeners != null && changeListeners.size() > 0) {
            Collections.sort(changeListeners);
            for (ProductChangeListener listener : changeListeners) {
                try {
                    listener.create(bean);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    @Override
    public ProductResponse update(ProductDataRequest request) {
        ProductResponse result = new ProductResponse();
        if (request.getId() == null) {
            result.setCode(501);
            result.setMsg("无效id");
            return result;
        }
        Product bean = dataDao.findById(request.getId());
        if (bean == null) {
            result.setCode(502);
            result.setMsg("无效id");
            return result;
        }
        handleData(request, bean);

        imageDao.deleteByProduct(request.getId());
        //处理图片
        if (request.getImages() != null && request.getImages().size() > 0) {
            for (ProductImageSimple item : request.getImages()) {
                ProductImage image = new ProductImage();
                image.setProduct(bean);
                image.setUrl(item.getUrl());
                image.setTenant(bean.getTenant());
                imageDao.save(image);
            }
        }
        specDao.deleteByProduct(request.getId());
        //处理规格
        if (request.getSpecs() != null && request.getSpecs().size() > 0) {
            for (ProductSpecVo spec : request.getSpecs()) {
                ProductSpec ProductSpec = new ProductSpec();
                ProductSpec.setProduct(bean);
                ProductSpec.setName(spec.getName());
                ProductSpec.setTenant(bean.getTenant());
                specDao.save(ProductSpec);
                if (spec.getValues() != null && spec.getValues().size() > 0) {
                    for (ProductSpecValueVo value : spec.getValues()) {
                        ProductSpecValue specValue = new ProductSpecValue();
                        specValue.setProductSpec(ProductSpec);
                        specValue.setValue(value.getName());
                        specValue.setTenant(bean.getTenant());
                        specValueDao.save(specValue);
                    }
                }

            }
        }

        updateSkus(request, bean);


        //处理属性
//        if (request.getAttrs() != null && request.getAttrs().size() > 0) {
//            bean.setAttrs(new HashSet<>());
//            for (Long attr : request.getAttrs()) {
//                ProductAttrValue value = attrValueDao.findById(attr);
//                if (value != null) {
//                    bean.getAttrs().add(value);
//                }
//            }
//        }
        result = new ProductResponseConvert().conver(bean);

        if (changeListeners != null && changeListeners.size() > 0) {
            Collections.sort(changeListeners);
            for (ProductChangeListener listener : changeListeners) {
                try {
                    listener.create(bean);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

        
        
        result = new ProductResponseConvert().conver(bean);
        return result;
    }

    @Override
    public ProductResponse offLine(ProductDataRequest request) {
        ProductResponse result = new ProductResponse();
        Product bean = dataDao.findById(request.getTenant(), request.getId());
        if (bean == null) {
            result.setCode(1000);
            result.setMsg("无效id");
            return result;
        }
        bean.setProductState(ProductState.lowerShelf);
        return result;
    }

    @Override
    public ProductResponse onLine(ProductDataRequest request) {
        ProductResponse result = new ProductResponse();
        Product bean = dataDao.findById(request.getTenant(), request.getId());
        if (bean == null) {
            result.setCode(1000);
            result.setMsg("无效id");
            return result;
        }
        bean.setProductState(ProductState.onSale);
        return result;
    }

    private void updateSkus(ProductDataRequest request, Product bean) {
        List<ProductSku> values = bean.getSkus();
        List<ProductSku> allList = new ArrayList<>();
        //处理sku
        if (request.getSkus() != null && request.getSkus().size() > 0) {
            for (ProductSkuSimple item : request.getSkus()) {
                ProductSku sku;
                if (item.getId() == null) {
                    sku = new ProductSku();
                    skuDao.save(sku);
                } else {
                    sku = value(bean.getSkus(), item.getId());
                }
                if (sku == null) {
                    sku = new ProductSku();
                    skuDao.save(sku);
                }
                if (item.getSalePrice() == null) {
                    item.setSalePrice(new BigDecimal(0));
                }
                if (item.getMarketPrice() == null) {
                    item.setMarketPrice(new BigDecimal(0));
                }
                sku.setSalePrice(item.getSalePrice());
                sku.setName(item.getName());
                sku.setMarketPrice(item.getMarketPrice());
                sku.setSpec(item.getSpec());
                sku.setProduct(bean);
                sku.setTenant(bean.getTenant());
                allList.add(sku);


            }

            //获取最大价格和最低价格
            List<BigDecimal> moneys = request.getSkus().stream().map(item -> item.getSalePrice()).collect(Collectors.toList());
            BigDecimal min = moneys.stream().min(new Comparator<BigDecimal>() {
                @Override
                public int compare(BigDecimal bigDecimal, BigDecimal t1) {
                    return bigDecimal.compareTo(t1);
                }
            }).get();

            BigDecimal max = moneys.stream().max(new Comparator<BigDecimal>() {
                @Override
                public int compare(BigDecimal bigDecimal, BigDecimal t1) {
                    return bigDecimal.compareTo(t1);
                }
            }).get();
            bean.setMinPrice(min);
            bean.setMaxPrice(max);
            bean.setProductType(ProductType.sku);
            bean.setSkuEnable(true);
            bean.setSalePrice(min);
        } else {
            bean.setProductType(ProductType.spu);
            bean.setSkuEnable(false);
        }
        values.removeAll(allList);
        if (values.size() > 0) {
            for (ProductSku item : values) {
                skuDao.delete(item);
            }
        }

    }
    public ProductSku value(List<ProductSku> values, Long id) {
        if (values != null && values.size() > 0) {
            for (ProductSku value : values) {
                if (value.getId().equals(id)) {
                    return value;
                }
            }
        }
        return null;
    }
    private void handleData(ProductDataRequest request, Product bean) {
        TenantBeanUtils.copyProperties(request, bean);
        if (request.getCreator() != null) {
            bean.setCreator(creatorDao.findById(request.getCreator()));
        }
        if (request.getProductGroup() != null) {
            bean.setProductGroup(productGroupDao.findById(request.getProductGroup()));
        }
        if (request.getShop() != null) {
            bean.setShop(shopDao.findById(request.getShop()));
        }
        if (request.getProductCatalog() != null) {
            bean.setProductCatalog(productCatalogDao.findById(request.getProductCatalog()));
        }

    }

    @Override
    public ProductResponse delete(ProductDataRequest request) {
        ProductResponse result = new ProductResponse();
        if (request.getId() == null) {
            result.setCode(501);
            result.setMsg("无效id");
            return result;
        }
        dataDao.deleteById(request.getTenant(), request.getId());
        return result;
    }

    @Override
    public ProductResponse view(ProductDataRequest request) {
        ProductResponse result = new ProductResponse();
        Product bean = dataDao.findById(request.getTenant(), request.getId());
        if (bean == null) {
            result.setCode(1000);
            result.setMsg("无效id");
            return result;
        }
        result = new ProductResponseConvert().conver(bean);
        return result;
    }

    @Override
    public ProductList list(ProductSearchRequest request) {
        ProductList result = new ProductList();

        List<Filter> filters = new ArrayList<>();
        filters.add(Filter.eq("tenant.id", request.getTenant()));
        filters.addAll(FilterUtils.getFilters(request));
        List<Order> orders = new ArrayList<>();
        if ("asc".equals(request.getSortMethod())) {
            orders.add(Order.asc("" + request.getSortField()));
        } else if ("desc".equals(request.getSortMethod())) {
            orders.add(Order.desc("" + request.getSortField()));
        } else {
            orders.add(Order.desc("id"));
        }
        List<Product> organizations = dataDao.list(0, request.getSize(), filters, orders);

        ProductSimpleConvert convert = new ProductSimpleConvert();
        ConverResourceUtils.converList(result, organizations, convert);
        return result;
    }

    @Override
    public ProductPage search(ProductSearchRequest request) {
        ProductPage result = new ProductPage();
        Pageable pageable = new PageableConver().conver(request);
        pageable.getFilters().addAll(FilterUtils.getFilters(request));
        pageable.getFilters().add(Filter.eq("tenant.id", request.getTenant()));
        if ("asc".equals(request.getSortMethod())) {
            pageable.getOrders().add(Order.asc("" + request.getSortField()));
        } else if ("desc".equals(request.getSortMethod())) {
            pageable.getOrders().add(Order.desc("" + request.getSortField()));
        } else {
            pageable.getOrders().add(Order.desc("id"));
        }
        Page<Product> page = dataDao.page(pageable);

        ProductSimpleConvert convert = new ProductSimpleConvert();
        ConverResourceUtils.converPage(result, page, convert);
        return result;
    }
}
